library ieee;
use ieee.std_logic_1164.all;
use IEEE.NUMERIC_STD.all;
use work.typeDefinitions.all;

entity fetchStage is
  port (
    clk        : in std_logic;
    nReset     : in std_logic;
    holdStage  : in std_logic;
    invalidate : in std_logic;

    sel      : in pcSel;
    busA     : in std_logic_vector(31 downto 0);
    jumpAddr : in std_logic_vector(25 downto 0);

    iMemAddr : out std_logic_vector(31 downto 0);  --need more signals?

    iMemData    : in  std_logic_vector(31 downto 0);
    pcOld_in    : in  std_logic_vector(31 downto 0);
    default     : in  std_logic_vector (31 downto 0);
    halt        : in  std_logic;
    holdPC      : in  std_logic;
    pcOld       : out std_logic_vector(31 downto 0);
    instruction : out std_logic_vector(31 downto 0);
    nPC         : out std_logic_vector(31 downto 0));

end fetchStage;

architecture fetchStage_arch of fetchStage is

  signal pcplusfour : std_logic_vector (31 downto 0);
  signal pcout      : std_logic_vector (31 downto 0);

  component fetchInterstageReg
    port (
      clk            : in  std_logic;
      nReset         : in  std_logic;
      holdStage      : in  std_logic;
      invalidate     : in  std_logic;
      halt           : in  std_logic;
      pcOld_in       : in  std_logic_vector(31 downto 0);
      nPC_in         : in  std_logic_vector(31 downto 0);
      instruction_in : in  std_logic_vector(31 downto 0);
      instruction    : out std_logic_vector(31 downto 0);
      pcOld          : out std_logic_vector(31 downto 0);
      nPC            : out std_logic_vector(31 downto 0));
  end component;


  component programCounter
    port
      (
        clk        : in  std_logic;
        nReset     : in  std_logic;
        memWait    : in  std_logic;
        sel        : in  pcSel;
        jumpAddr   : in  std_logic_vector (25 downto 0);
        busA       : in  std_logic_vector (31 downto 0);
        pcOld      : in  std_logic_vector(31 downto 0);
        default    : in  std_logic_vector(31 downto 0);
        halt       : in  std_logic;
        pcplusfour : out std_logic_vector (31 downto 0);
        pcout      : out std_logic_vector (31 downto 0)
        );
  end component;

  signal stopStage : std_logic;
begin  -- fetchInterstageReg

  iMemAddr  <= pcout;
  stopStage <= holdStage or halt;
  
  interstage_c : fetchInterstageReg port map (
    clk            => clk,
    nReset         => nReset,
    holdStage      => stopStage,
    invalidate     => invalidate,
    pcOld_in       => pcout,
    pcOld          => pcOld,
    halt           => halt,
    nPC_in         => pcplusfour,
    instruction_in => iMemData,
    instruction    => instruction,
    nPC            => nPC);

  programcounter_c : programCounter port map (
    clk        => clk,
    nReset     => nReset,
    memWait    => holdPC,
    sel        => sel,
    jumpAddr   => jumpAddr,
    busA       => busA,
    pcOld      => pcOld_in,
    default    => default,
    halt       => halt,
    pcplusfour => pcplusfour,
    pcout      => pcout);



end fetchStage_arch;
